#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "FileMangent/fileMangent.h"
#include <QLabel>
#include <QApplication>
#include <QGuiApplication> // 在文件顶部添加此行
#include <QScreen>
#include <QMessageBox>
#include <memory>
#include <QDirIterator>

static void loadStyle(QWidget * object, const QString& styleSheetPath);
static bool isSupportedMediaFile(const QString &filePath);
PlayMangent& player = PlayMangent::get_instance();
PlayMangent * m_player_ptr = &player;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow)
    ,isInit(false)
{
    ui->setupUi(this);
    // 初始化UI控件
    _init();

    // 连接信号和槽: 当接收到文件信息时，调用 onFileInformationReceived 方法
    connect(&FileMangent::get_instance(), &FileMangent::fileInformationReceived, this, &MainWindow::onFileInformationReceived);
    player.registerFileMangent();
    resize(1440, 684); // Set default window size
    centerDisplay(); // Center the window on the screen

    isInit = true;
}
/***************************************************************
 *  @note      Function to handle button click events
 *  @param     buttonType Type of the button that was clicked
 *  @return    None
 ***************************************************************/
void MainWindow::handleButtonClick(ButtonType buttonType) {
    switch (buttonType) {
        case PlayButton:
            m_player_ptr->play();
            // 在这里执行播放按钮的操作
            break;
        case StopButton:
            m_player_ptr->stop();
            // 在这里执行停止按钮的操作
            break;
        case PauseButton:
            m_player_ptr->pause();
            // 在这里执行暂停按钮的操作
            break;
        case NextButton:
            m_player_ptr->play_next();
            // 在这里执行下一首按钮的操作
            break;
        case PreviousButton:
            m_player_ptr->play_previous();
            // 在这里执行上一首按钮的操作
            break;
        default:
            break;
    }
}
/***************************************************************
 *  @note      Function to deal speed selector change event
 *  @param     None
 *  @return    None
 ***************************************************************/
void MainWindow::onSpeedSelectorChanged(int a) {
    std:: cout << "Speed selector changed to " << a << std::endl;
}
/***************************************************************
 *  @note      Slot for handling add files button click event
 *  @param     None
 *  @return    None
 ***************************************************************/
void MainWindow::onButton_openFileclicked()
{
    // 打开文件或目录
    QString dir = QFileDialog::getOpenFileName(this, tr("选择要播放的目录或文件"), "E:\\Music", tr("音视频文件 (*.wma *.wav *.flac *.mp3 *.aac *.ogg *.mp4);;所有文件 (*)"));
    if (!dir.isEmpty()) {
        qDebug() << "Selected directory or file:" << dir;
        QFileInfo fileInfo(dir);

        if (fileInfo.isDir()) {
            QMessageBox::StandardButton reply;
            reply = QMessageBox::question(this, tr("添加目录下的所有支持的文件？"), tr("你想添加目录下的所有支持的文件吗？"), QMessageBox::Yes | QMessageBox::No);
            if (reply == QMessageBox::Yes) {
                QDirIterator it(dir, QDir::Files, QDirIterator::Subdirectories);
                while (it.hasNext()) {
                    QString filePath = it.next();
                    if (isSupportedMediaFile(filePath)) {
                        qDebug() << "File:" << filePath;
                        // 添加文件到播放列表
                        m_player_ptr->addfile(filePath.toStdString());
                    } else {
                        qDebug() << "Unsupported file format:" << filePath;
                    }
                }
            }
        } else if (fileInfo.isFile()) {
            if (isSupportedMediaFile(dir)) {
                qDebug() << "Selected file:" << dir;
                // 添加文件到播放列表
                m_player_ptr->addfile(dir.toStdString());
            } else {
                qDebug() << "Unsupported file format:" << dir;
                QMessageBox::information(this, tr("不支持的文件格式"), tr("所选文件格式不受支持，请选择支持的音频或视频文件。"));
            }
        }
    }
}
/***************************************************************
 *  @note      Slot for handling toggle resize button click event
 *  @param     checked Boolean indicating whether the button is checked
 *  @return    None
 ***************************************************************/
void MainWindow::onToggleResizeButtonClicked(bool checked)
{
//    qDebug()<<__FUNCTION__<<"checked:"<<checked;
    if (checked) {
        // Allow resizing
        setMinimumSize(QSize(0, 0));
        setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
        // Enable maximize button
        setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint);
    } else {
        // Prevent resizing
        setFixedSize(size());
        // Disable maximize button
        setWindowFlags(windowFlags() & ~Qt::WindowMaximizeButtonHint);
    }
    if(isInit){
        // Apply the new window flags
        show();
    }
}
/***************************************************************
 *  @note      Slot for handling file information received event
 *  @param     info FileInfo object containing the received file information
 *  @return    None
 ***************************************************************/
void MainWindow::onFileInformationReceived(const FileInfo& info) {
    labelFilename->setText(QString("Filename: %1").arg(QString::fromStdString(info.filename)));

    int durationInSeconds = static_cast<int>(info.duration);
    std::cout << "Duration in seconds: " << durationInSeconds << std::endl;
    int hours = durationInSeconds / 3600;
    int minutes = (durationInSeconds % 3600) / 60;
    int seconds = durationInSeconds % 60;

    labelDuration->setText(QString("Duration: %1:%2:%3").arg(hours, 2, 10, QChar('0')).arg(minutes, 2, 10, QChar('0')).arg(seconds, 2, 10, QChar('0')));

    labelBitrate->setText(QString("Bitrate: %1 Kbit/s").arg(info.bitrate));
    labelMediaType->setText(QString("Media Type: %1").arg(QString::fromStdString(info.media_type)));
    labelAudioType->setText(QString("Audio Type: %1").arg(QString::fromStdString(info.audio_type)));
    video_widget->setTotalTime(durationInSeconds);
    if( m_player_ptr->status()== PlayStatus::IDLING || m_player_ptr->status()== PlayStatus::STOPPED || m_player_ptr->status()== PlayStatus::PAUSED){
        m_player_ptr->play();
        updateStatus(true);
    }
}
void MainWindow::onPlaybackStopped(){
    qDebug()<<"MainWindows onPlaybackStopped";
    // 提供 onPlaybackStopped 方法的具体实现
    updateStatus(false);
    //clean onFileInformationReceived text info
    labelFilename->setText(QString("Filename: "));
    labelDuration->setText(QString("Duration: "));
    labelBitrate->setText(QString("Bitrate: "));
    labelMediaType->setText(QString("Media Type: "));
    labelAudioType->setText(QString("Audio Type: "));
}
void MainWindow::onPlaybackStarted(){
    qDebug()<<"MainWindows onPlaybackStarted";
    // 提供 onPlaybackStarted 方法的具体实现
}
/***************************************************************
 *  @note      Function to initialize the main window
 *  @param     None
 *  @return    None
 ***************************************************************/
void MainWindow::_init(){
    // 创建主布局
    createMainLayout();
    // 添加限制窗口大小的按钮,设置为true，表示默认窗口大小可变
    createToggleResizeButton(true);

    // 创建视频窗口区域
    createVideoArea();
    // 创建按钮区域
    createButtonArea();
    // 创建信息区域
    createInfoArea();

}
/***************************************************************
 *  @note      Function to create the toggle resize button
 *  @param     state Boolean indicating whether the button is checked    
 *  @return    None
 ***************************************************************/
void MainWindow::createToggleResizeButton(bool state)
{
    toggleResizeButton = new QToolButton(this);
    toggleResizeButton->setText("Variable window");
    toggleResizeButton->setCheckable(true);  // 设置按钮为可选中状态
    QMetaObject::Connection connection = connect(toggleResizeButton, &QToolButton::toggled, this, &MainWindow::onToggleResizeButtonClicked);
    if(!connection) {
        qDebug() << "Failed to connect";
    }

    QToolBar *toolBar = addToolBar("Resize ToolBar");
    toolBar->addWidget(toggleResizeButton);

    // Set toggleResizeButton to checked state
    onToggleResizeButtonClicked(state);
    toggleResizeButton->setChecked(state);
}
/***************************************************************
 *  @note      Function to create the main layout
 *  @param     None
 *  @return    None
 ***************************************************************/
void MainWindow::createMainLayout()
{
    main_layout = new QVBoxLayout(ui->centralwidget);
    main_layout->setContentsMargins(15, 15, 15, 15); // Left, right, top, and bottom margins
    main_layout->setSpacing(30); // Vertical spacing between controls
    main_layout->setAlignment(Qt::AlignTop); // Align the controls to the top of the window
}
/***************************************************************
 *  @note      Function to create the video widget
 *  @param     None
 *  @return    None
 ***************************************************************/
void MainWindow::createVideoArea()
{
    video_widget = new QVideoWidget();
    video_widget->setPlayMangent(&PlayMangent::get_instance());
    video_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    main_layout->addWidget(video_widget, 3); // Make video area occupy a larger proportion
}
/***************************************************************
 *  @note      Function to create the button area
 *  @param     None
 *  @return    None
 ***************************************************************/
void MainWindow::createButtonArea()
{
    createButtons();
    loadButtonStyleSheet(":/button_style.css");
}
/***************************************************************
 *  @note      Function to create info area
 *  @param     None
 *  @return    None
 ***************************************************************/
void MainWindow::createInfoArea(){
    // 创建状态标签
    createStatusLabel();
    // 创建状态栏
    createStatusFilenameLayout();
    // 创建状态栏
    createStatusLayout();
}
/***************************************************************
 *  @note      Function to create the buttons
 *  @param     None
 *  @return    None
 ***************************************************************/
void MainWindow::createButtons()
{
    // 创建停止按钮
    button_stop = new QPushButton("&stop", this);
    button_stop->setObjectName("button_stop");

    // 创建暂停按钮
    button_pause = new QPushButton("&pause", this);
    button_pause->setObjectName("button_pause");

    // 创建下一个按钮
    button_next = new QPushButton("&next", this);
    button_next->setObjectName("button_next");

    // 创建播放速度选择器
    speed_selector = new QComboBox(this);
    speed_selector->addItem("1x");
    speed_selector->addItem("1.5x");
    speed_selector->addItem("0.5x");
    speed_selector->addItem("2x");
    speed_selector->addItem("5x");
    speed_selector->setObjectName("speed_selector");

    // 创建上一个按钮
    button_previous = new QPushButton("&previous", this);
    button_previous->setObjectName("button_previous");

    // 创建播放按钮
    button_play = new QPushButton("&play", this);
    button_play->setObjectName("button_play");

    // 创建打开文件按钮
    button_openFile = new QPushButton("&open", this);
    button_openFile->setObjectName("button_open");

    // 创建网格布局管理器
    button_layout = new QGridLayout();

    // 在第一行添加按钮
    button_layout->addWidget(button_play, 0, 0); 
    button_layout->addWidget(button_stop, 0, 1);
    button_layout->addWidget(button_pause, 0, 2);
    button_layout->addWidget(button_previous, 0, 3);
    button_layout->addWidget(button_next, 0, 4);

    button_layout->addWidget(speed_selector, 0, 5);

    // 在第二行添加打开文件按钮
    button_layout->addWidget(button_openFile, 1, 0, 1, 6);

    // 将网格布局添加到主布局
    main_layout->addLayout(button_layout);

    // 连接按钮和槽函数
    connect(button_openFile,SIGNAL(clicked()),this,SLOT(onButton_openFileclicked()));
    connect(button_stop,SIGNAL(clicked()),this,SLOT(onStopButtonClicked()));
    connect(button_pause,SIGNAL(clicked()),this,SLOT(onPauseButtonClicked()));
    connect(button_next,SIGNAL(clicked()),this,SLOT(onNextButtonClicked()));
    connect(button_previous,SIGNAL(clicked()),this,SLOT(onPreviousButtonClicked()));
    connect(button_play,SIGNAL(clicked()),this,SLOT(onPlayButtonClicked()));
    connect(speed_selector,SIGNAL(currentIndexChanged(int)),this,SLOT(onSpeedSelectorChanged(int)));
}


/***************************************************************
 *  @note      Function to create the status label
 *  @param     None
 *  @return    None
 ***************************************************************/
void MainWindow::createStatusLabel()
{
    fileInfoWidget = new QWidget(this);
    fileInfoLayout = new QGridLayout(fileInfoWidget);
    fileInfoLayout->setSpacing(20); // Adjust the spacing value as needed
    labelFilename = new QLabel("Filename: ");
    labelDuration = new QLabel("Duration: ");
    labelBitrate = new QLabel("Bitrate: ");
    labelMediaType = new QLabel("Media Type: ");
    labelAudioType = new QLabel("Audio Type: ");

    // Arrange labels in a 3x2 grid
    fileInfoLayout->addWidget(labelFilename, 0, 0, 1, 2); // rowspan=1, colspan=2
    fileInfoLayout->addWidget(labelDuration, 1, 0);
    fileInfoLayout->addWidget(labelBitrate, 1, 1);
    fileInfoLayout->addWidget(labelMediaType, 2, 0);
    fileInfoLayout->addWidget(labelAudioType, 2, 1);

    // 将 fileInfoWidget 添加到布局中的适当位置（例如在 statusBar 旁边）
    label_status = new QLabel("Stopped", this);
    // Adjust the label size (width and height)
    label_status->setFixedSize(60, 50);
    updateStatus(false);
    // 设置楷体字体和加粗
    QFont font("KaiTi", 10, QFont::Bold, true);

    // 设置棕色
    QPalette palette;
    palette.setColor(QPalette::WindowText, QColor(139, 69, 19)); // 此为棕色的RGB值

    // 为每个标签设置字体和颜色
    QList<QLabel*> labels = {labelFilename, labelDuration, labelBitrate, labelMediaType, labelAudioType};
    for (QLabel* label : labels) {
        label->setFont(font);
        label->setPalette(palette);
    }
}

/***************************************************************
 *  @note      Function to create the status filename layout
 *  @param     None
 *  @return    None
 ***************************************************************/
void MainWindow::createStatusFilenameLayout()
{
    status_filename_layout = new QHBoxLayout();
    status_filename_layout->addWidget(label_status);
    status_filename_layout->addWidget(fileInfoWidget); // Use fileInfoWidget instead of fileInfoLabel
    status_filename_layout->setSpacing(20); // Horizontal spacing between controls
}
/***************************************************************
 *  @note      Function to create the status layout
 *  @param     None
 *  @return    None
 ***************************************************************/
void MainWindow::createStatusLayout()
{
    status_layout = new QVBoxLayout();
    status_layout->addLayout(status_filename_layout);
    status_layout->setSpacing(40); // Vertical spacing between controls

    main_layout->addLayout(status_layout, 1); // Make status label and button area occupy a smaller proportion
    main_layout->setSpacing(40); // Vertical spacing between controls
}
/***************************************************************
 *  @note      Function to center the window
 *  @param     None
 *  @return    None
 ***************************************************************/
void MainWindow::centerDisplay(){
    // 居中显示窗口
    QScreen* screen = QGuiApplication::primaryScreen();
    // 获取屏幕的宽度和高度
    QRect screenGeometry = screen->geometry();
    int screenWidth = screenGeometry.width();
    int screenHeight = screenGeometry.height();
    int windowWidth = this->width();
    int windowHeight = this->height();
    // 将窗口移动到屏幕中央
    this->setGeometry((screenWidth - windowWidth) / 2, (screenHeight - windowHeight) / 2, windowWidth, windowHeight);
}
/***************************************************************
 *  @note      Destructor for the MainWindow class
 *  @param     None
 *  @return    None
 ***************************************************************/
MainWindow::~MainWindow()
{
    qApp->setStyleSheet("");
    delete ui;
}
/***************************************************************
 *  @note      Slots for handling button click events
 *  @param     None
 *  @return    None
 *  @details   These slots handle the click events of the stop, pause, next, previous buttons.
 *             They call the handleButtonClick function with the appropriate button type.
 ***************************************************************/
void MainWindow::onStopButtonClicked() {
    handleButtonClick(StopButton);
}
void MainWindow::onPauseButtonClicked() {
    handleButtonClick(PauseButton);
}
void MainWindow::onNextButtonClicked() {
    handleButtonClick(NextButton);
}
void MainWindow::onPreviousButtonClicked() {
    handleButtonClick(PreviousButton);
}
void MainWindow::onPlayButtonClicked() {
    handleButtonClick(PlayButton);
}
/***************************************************************
 *  @note      Function to update the status
 *  @param     isActive Boolean indicating whether the status is active
 *  @return    None
 ***************************************************************/
void MainWindow::updateStatus(bool isActive)
{
    if (isActive)
    {
        label_status->setStyleSheet("QLabel { border: 2px solid #000; border-radius: 20px; min-width: 20px; min-height: 40px; color: #000; background-color: #0f0; }");
        label_status->setText("Active");
    }
    else
    {
        label_status->setStyleSheet("QLabel { border: 2px solid #000; border-radius: 20px; min-width: 20px; min-height: 40px; color: #000; background-color: #f00; }");
        label_status->setText("Stopped");
    }
}
/***************************************************************
 *  @note      Function to load the button style sheet
 *  @param     filePath Path to the style sheet file
 *  @return    None
 ***************************************************************/
void MainWindow::loadButtonStyleSheet(const QString &filePath)
{
    QFile file(filePath);
    if (file.exists()) {
        if (file.open(QFile::ReadOnly)) {
            QString styleSheet = QString::fromLatin1(file.readAll());
            qApp->setStyleSheet(styleSheet);
            file.close();
        }
    }
    else {
        qDebug() << "Cannot find file:" << filePath;
    }
}
/***************************************************************
 *  @note      Function to load the style sheet
 *  @param     object Pointer to the object to which the style sheet is to be applied
 *  @return    None
 ***************************************************************/
[[maybe_unused]]  static void loadStyle(QWidget * object, const QString& styleSheetPath)
{
        QFile file(styleSheetPath);
        if (!file.open(QFile::ReadOnly | QFile::Text))
        {
            qWarning("Failed to open stylesheet file.");
            return;
        }

        QString styleSheet = QString::fromUtf8(file.readAll());
        object->setStyleSheet(styleSheet);
}
/***************************************************************
 *  @note      Function to check if a file is a supported media file
 *  @param     filePath Path to the file to be checked
 *  @return    Boolean indicating whether the file is a supported media file
 ***************************************************************/
static bool isSupportedMediaFile(const QString &filePath) {
    QFileInfo fileInfo(filePath);
    QString fileExtension = fileInfo.suffix().toLower();
    QStringList supportedExtensions = {"wma", "wav", "flac", "mp3", "aac", "ogg", "mp4"};

    return supportedExtensions.contains(fileExtension);
}
